using System;
using System.Collections;
using System.Collections.Specialized;
using System.Text;
using System.Web.UI;
using Iesi.Collections;
using Sedna.Core.Common;
using Sedna.Core.Persistence;
using Spring.Util;

namespace Sedna.Core.Controller
{        
    public abstract class BaseController : IController
    {
        private const String DATA_PROVIDER_KEY = "dataProvider";

        private String dataProviderPath;

        private String contextKey;

        private Control control;        

        # region Properties

        public String DataProviderPath
        {
            get { return dataProviderPath; }
            set { dataProviderPath = value; }
        }        

        public IDictionary ControllerContext
        {
            get
            {
                if (!(ExecutionContext.Current.GetScopedValue(ContextKey, Scope.Page) is IDictionary))
                {
                    ExecutionContext.Current.SetScopedValue(ContextKey, new Hashtable(), Scope.Page);
                }

                return (IDictionary)ExecutionContext.Current.GetScopedValue(ContextKey, Scope.Page);
            }
        }

        public virtual IDataProvider CurrentDataProvider
        {
            get { return (IDataProvider)ControllerContext[DATA_PROVIDER_KEY]; }
            set { ControllerContext[DATA_PROVIDER_KEY] = value; }
        }

        public Control Control
        {
            get { return control; }
            set
            {
                bool raiseEvent = (control != value);
                
                control = value;

                if (control != null)
                {
                    contextKey = String.Format("context.{0}", control.ID);
                }

                if (raiseEvent && OnControlChanged != null)
                    OnControlChanged(control);
            }
        }                

        # endregion

        # region Public Methods

        public abstract void LoadOrRefresh();

        public abstract void LoadNewData(IDataProvider dataProvider);
        
        public virtual void LoadNewData()
        {
            LoadNewData(NewDataProvider);
        }
        
        public virtual void Refresh()
        {
            if (CurrentDataProvider != null)
            {
                BindControl(CurrentDataProvider);
            }
        }

        # endregion

        # region Events
        
        public event ControlHandler OnControlChanged;
        
        # endregion

        protected abstract void BindControl(IDataProvider dataProvider);

        protected String ContextKey
        {
            get { return contextKey; }
        }

        protected IDataProvider NewDataProvider
        {
            get
            {
                if (!StringUtils.IsNullOrEmpty(DataProviderPath))
                {
                    return (IDataProvider)ExecutionContext.Current.GetPropertyValue(DataProviderPath);
                }

                return null;
            }
        }

        # region Get/Set By Path - Methods
        
        protected object GetObjectByPath(String path)
        {
            return ExecutionContext.Current.GetPropertyValue(path);
        }

        protected bool SetObjectByPath(String path, object obj)
        {
            if (StringUtils.IsNullOrEmpty(path))
                return false;

            ExecutionContext.Current.SetPropertyValue(path, obj);

            return true;
        }

        protected ICollection GetCollectionByPath(String path)
        {
            return ExecutionContext.Current.GetPropertyValue(path) as ICollection;
        }

        protected bool SetCollectionByPath(String path, ICollection collection)
        {
            if (StringUtils.IsNullOrEmpty(path))
                return false;

            ExecutionContext.Current.SetPropertyValue(path, collection);

            return true;
        }

        protected IList GetListByPath(String path)
        {
            if (!(ExecutionContext.Current.GetPropertyValue(path) is IList))
            {
                ExecutionContext.Current.SetPropertyValue(path, new ArrayList());
            }

            return (IList)ExecutionContext.Current.GetPropertyValue(path);
        }

        protected bool SetListByPath(String path, IList list)
        {
            if (StringUtils.IsNullOrEmpty(path))
                return false;

            ExecutionContext.Current.SetPropertyValue(path, list);

            return true;
        }

        protected ISet GetSetByPath(String path)
        {
            if (!(ExecutionContext.Current.GetPropertyValue(path) is ISet))
            {
                ExecutionContext.Current.SetPropertyValue(path, new ListSet());
            }

            return (ISet)ExecutionContext.Current.GetPropertyValue(path);
        }

        protected bool SetSetByPath(String path, ISet set)
        {
            if (StringUtils.IsNullOrEmpty(path))
                return false;
            
            ExecutionContext.Current.SetPropertyValue(path, set);
            
            return true;
        }

        protected IDictionary GetDictionaryByPath(String path)
        {
            if (!(ExecutionContext.Current.GetPropertyValue(path) is IDictionary))
            {
                ExecutionContext.Current.SetPropertyValue(path, new OrderedDictionary());
            }

            return (IDictionary)ExecutionContext.Current.GetPropertyValue(path);
        }

        protected bool SetDictionaryByPath(String path, IDictionary dictionary)
        {
            if (StringUtils.IsNullOrEmpty(path))
                return false;

            ExecutionContext.Current.SetPropertyValue(path, dictionary);

            return true;
        }

        # endregion

        # region Get From Context - Methods

        protected ICollection GetCollectionFromContext(String key)
        {
            return ControllerContext[key] as ICollection;
        }
        
        protected IList GetListFromContext(String key)
        {
            if (!(ControllerContext[key] is IList))
            {
                ControllerContext[key] = new ArrayList();
            }

            return (IList)ControllerContext[key];
        }

        protected ISet GetSetFromContext(String key)
        {
            if (!(ControllerContext[key] is ISet))
            {
                ControllerContext[key] = new ListSet();
            }

            return (ISet)ControllerContext[key];
        }

        protected IDictionary GetDictionaryFromContext(String key)
        {
            if (!(ControllerContext[key] is IDictionary))
            {
                ControllerContext[key] = new OrderedDictionary();
            }

            return (IDictionary)ControllerContext[key];
        }

        # endregion

        public object Clone()
        {
            return MemberwiseClone();
        }
    }
}
